package com.ikas.ai.server.module.analyse.algorithm;

/**
 * 四分位算法
 *
 * @author tang.xuandong
 * @version 1.0.0
 * @date 2023/4/18 11:45
 */

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.List;

public class QuartileCalculator {

    /**
     * 四分位算法
     *
     * @param data source
     * @return q1=data[0] q2=data[1] q3=data[2]
     */
    public static double[] calculateIQR(List<Double> data) {
        if (data == null || data.size() < 4) {
            return null;
        }
        // 转成BigDecimal类型，避免失去精度
        BigDecimal[] datas = new BigDecimal[data.size()];
        for (int i = 0; i < data.size(); i++) {
            datas[i] = BigDecimal.valueOf(data.get(i));
        }
        int len = datas.length;// 数组长度
        Arrays.sort(datas);    // 数组排序，从小到大
        BigDecimal q1;  // 第一四分位
        BigDecimal q2;  // 第二四分位
        BigDecimal q3;  // 第三四分位
        int index = 0;  // 记录下标
        // n代表项数，因为下标是从0开始所以这里理解为：len = n+1
        if (len % 2 == 0) { // 偶数
            index = new BigDecimal(len).divide(new BigDecimal("4")).intValue();
            q1 = datas[index - 1].multiply(new BigDecimal("0.25")).add(datas[index].multiply(new BigDecimal("0.75")));
            q2 = datas[len / 2].add(datas[len / 2 - 1]).divide(new BigDecimal("2"));
            index = new BigDecimal(3 * (len + 1)).divide(new BigDecimal("4")).intValue();
            q3 = datas[index - 1].multiply(new BigDecimal("0.75")).add(datas[index].multiply(new BigDecimal("0.25")));
        } else { // 奇数
            q1 = datas[new BigDecimal(len).multiply(new BigDecimal("0.25")).intValue()];
            q2 = datas[new BigDecimal(len).multiply(new BigDecimal("0.5")).intValue()];
            q3 = datas[new BigDecimal(len).multiply(new BigDecimal("0.75")).intValue()];
        }
        // 保留两位小数（四舍五入）
        double[] q = new double[3];
        q[0] = q1.setScale(3, RoundingMode.UP).doubleValue();
        q[1] = q2.setScale(3, RoundingMode.UP).doubleValue();
        q[2] = q3.setScale(3, RoundingMode.UP).doubleValue();
        return q;
    }


    /**
     * 求平均值
     *
     * @param nums nums
     * @return double
     */
    public static double avg(List<Double> nums) {
        double sum = 0.0;
        for (double v : nums) {
            sum += v;
        }
        return BigDecimal.valueOf(sum / nums.size()).setScale(3, RoundingMode.UP).doubleValue();
    }
}

